#include "PrecompiledHeaders.h"
#include "MenuOptions.h"

MenuOptions::MenuOptions()
{
    transparentBackground = true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// GAME STATE FUNCTIONS ///////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MenuOptions::enter(void)
{
    // Shows mouse
    CEGUI::MouseCursor::getSingleton().show();
    
    // Loads the MainMenu.layout script which places all of the main menu buttons on the screen
    CEGUI::Window* optionsSheet = CEGUI::WindowManager::getSingletonPtr()->loadWindowLayout("MenuOptions.layout");
    resources->GUISystem->setGUISheet(optionsSheet);
    
    // Attaches events to the Level Selection Menu buttons
    subscribeButton("MenuOptions/BackButton", &MenuOptions::clickBackButton, &MenuOptions::hoverBackButton, &MenuOptions::offBackButton);
    
    // Sets the radio buttons and sliders to their current values
    setRadioButtons();
    setSliders();
    
    // Subscribes the radio buttons and sliders to their associated events
    subscribeRadioButton("MenuOptions/RadioFirstPerson", &MenuOptions::clickPerspective);
    subscribeRadioButton("MenuOptions/RadioThirdPerson", &MenuOptions::clickPerspective);
    subscribeRadioButton("MenuOptions/RadioLowRes", &MenuOptions::clickResolution);
    subscribeRadioButton("MenuOptions/RadioMedRes", &MenuOptions::clickResolution);
    subscribeRadioButton("MenuOptions/RadioHighRes", &MenuOptions::clickResolution);
    subscribeRadioButton("MenuOptions/RadioMouse", &MenuOptions::clickInputDevice);
    subscribeRadioButton("MenuOptions/RadioKeyboard", &MenuOptions::clickInputDevice);
    subscribeRadioButton("MenuOptions/RadioJoystick", &MenuOptions::clickInputDevice);
    subscribeRadioButton("MenuOptions/RadioRandomSkybox", &MenuOptions::clickSkybox);
    subscribeRadioButton("MenuOptions/RadioTimedSkybox", &MenuOptions::clickSkybox);
	subscribeRadioButton("MenuOptions/RadioFSAA0", &MenuOptions::clickFSAA);
	subscribeRadioButton("MenuOptions/RadioFSAA2", &MenuOptions::clickFSAA);
	subscribeRadioButton("MenuOptions/RadioFSAA4", &MenuOptions::clickFSAA);
	subscribeRadioButton("MenuOptions/RadioFSAA6", &MenuOptions::clickFSAA);
    subscribeSlider("MenuOptions/SliderBGM", &MenuOptions::changeBGM);
    subscribeSlider("MenuOptions/SliderSFX", &MenuOptions::changeSFX);

	// Initialises the menu index
    winIterator = activeWindows.begin();
	
	// Sets and subscribes the checkbox
	CEGUI::Checkbox *chkboxFSM = (CEGUI::Checkbox*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/FSMCheckbox");
	chkboxFSM->subscribeEvent(CEGUI::Checkbox::EventCheckStateChanged, CEGUI::Event::Subscriber(&MenuOptions::clickFSM, this));
	if (resources->config->isFullScreen()) chkboxFSM->setSelected(true);
	addWinPos(chkboxFSM, false);
    
    // Set the background for pause menu
    if(transparentBackground) {
        setWindowImage("MainMenu/Background", "set:MenuBackground3 image:TransparentBackground");
    }
}

// Exits the MenuOptions
void MenuOptions::exit(void)
{
    CEGUI::MouseCursor::getSingleton().hide();
    CEGUI::WindowManager::getSingleton().destroyAllWindows();
	activeWindows.clear();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// EVENT HANDLER FUNCTIONS ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Sets the radio buttons so that the currently selected options are selected in the radio buttons
void MenuOptions::setRadioButtons()
{
    // Sets the perspective selected radio buttons
    if (resources->current_camera == resources->first_person_camera)
    {
        CEGUI::RadioButton *radioFirstPerson = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioFirstPerson");
        radioFirstPerson->setSelected(true);
    }
    else
    {
        CEGUI::RadioButton *radioThirdPerson = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioThirdPerson");
        radioThirdPerson->setSelected(true);
    }
    // Sets the resolution selected radio buttons
    if (resources->config->getResolutionHeight() == 600)
    {
        CEGUI::RadioButton *radioLowRes = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioLowRes");
        radioLowRes->setSelected(true);
    }
    else if (resources->config->getResolutionHeight() == 768)
    {
        CEGUI::RadioButton *radioMedRes = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioMedRes");
        radioMedRes->setSelected(true);
    }
    else
    {
        CEGUI::RadioButton *radioHighRes = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioHighRes");
        radioHighRes->setSelected(true);
    }
    // If pod is being used then the labels are changed so that they display the correct resolutions
    if (resources->pod_config_file)
    {
        setWindowText("MenuOptions/RadioLowRes", " 2400x600");
        setWindowText("MenuOptions/RadioMedRes", " 3072x768");
        setWindowText("MenuOptions/RadioHighRes", " 3840x1024");
    }
    // Sets the input device selected radio buttons
    if (resources->current_device == (InputDevice *)resources->mouse)
    {
        CEGUI::RadioButton *radioMouse = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioMouse");
        radioMouse->setSelected(true);
    }
    else if (resources->current_device == (InputDevice *)resources->keyboard)
    {
        CEGUI::RadioButton *radioKeyboard = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioKeyboard");
        radioKeyboard->setSelected(true);
    }
    else
    {
        CEGUI::RadioButton *radioJoystick = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioJoystick");
        radioJoystick->setSelected(true);
    }
    // Sets the skybox selected radio buttons
    if (resources->config->getSkyBoxMode())
    {
        CEGUI::RadioButton *radioRandom = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioRandomSkybox");
        radioRandom->setSelected(true);
    }
    else
    {
        CEGUI::RadioButton *radioTimed = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioTimedSkybox");
        radioTimed->setSelected(true);
    }
	// Sets the FSAA radio buttons
	CEGUI::RadioButton *radioFSAA = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/RadioFSAA" + resources->config->getFSAA());
	radioFSAA->setSelected(true);
}

// Sets the sliders so that the currently selected options are selected in the radio buttons
void MenuOptions::setSliders()
{
    CEGUI::Slider *sliderBGM = (CEGUI::Slider*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/SliderBGM");
    sliderBGM->setCurrentValue(resources->config->getVolumeBGM());
    CEGUI::Slider *sliderSFX = (CEGUI::Slider*)CEGUI::WindowManager::getSingleton().getWindow("MenuOptions/SliderSFX");
    sliderSFX->setCurrentValue(resources->config->getVolumeSFX());
}

// This function subscribes a radio button to an event when clicked upon
void MenuOptions::subscribeRadioButton(Ogre::String buttonName, bool(MenuOptions::* f1)(const CEGUI::EventArgs &))
{
    CEGUI::RadioButton *button = (CEGUI::RadioButton*)CEGUI::WindowManager::getSingleton().getWindow(buttonName);
    button->subscribeEvent(CEGUI::RadioButton::EventSelectStateChanged, CEGUI::Event::Subscriber(f1, this));
	addWinPos(button, false);
}

// This function subscribes a slider to an event when changed
void MenuOptions::subscribeSlider(Ogre::String sliderName, bool(MenuOptions::* f1)(const CEGUI::EventArgs &))
{
    CEGUI::Slider *slider = (CEGUI::Slider*)CEGUI::WindowManager::getSingleton().getWindow(sliderName);
    slider->subscribeEvent(CEGUI::Slider::EventValueChanged, CEGUI::Event::Subscriber(f1, this));
}

// Returns to main menu by popping the options menu state
bool MenuOptions::clickBackButton(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
	unsubscribeButton("MenuOptions/BackButton");
    if (resources->pod_config_file)
        resources->config->save(Constants::POD_CONFIG_FILE);
    else
        resources->config->save(Constants::CONFIG_FILE);
    popGameState();
    return true;
}

// Changes the appearance of the back button to signify the mouse hovering over the button
bool MenuOptions::hoverBackButton(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_OVER);
    setWindowText("MenuOptions/BackButton", "[back]");
    return true;
}

// Resets the appearance of the back button to signify the mouse cursor leaving the button area
bool MenuOptions::offBackButton(const CEGUI::EventArgs &e)
{
    setWindowText("MenuOptions/BackButton", "back");
    return true;
}

// Changes the current perspective based upon what the user has selected
bool MenuOptions::clickPerspective(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
    int currentChoice = ((CEGUI::RadioButton*)((const CEGUI::WindowEventArgs&)e).window)->getSelectedButtonInGroup()->getID();
    if (currentChoice == 101)
    {
        resources->current_camera = resources->first_person_camera;
    }
    else
    {
        resources->current_camera = resources->third_person_camera;
    }
    return true;
}

// Changes the current resolution based upon what the user has selected
bool MenuOptions::clickResolution(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
    int currentChoice = ((CEGUI::RadioButton*)((const CEGUI::WindowEventArgs&)e).window)->getSelectedButtonInGroup()->getID();
    // If pod is being used then a higher width resolution is required
    if (resources->pod_config_file)
    {
        if (currentChoice == 201)
        {
            resources->config->setResolutionWidth(2400);
            resources->config->setResolutionHeight(600);
        }
        else if (currentChoice == 202)
        {
            resources->config->setResolutionWidth(3072);
            resources->config->setResolutionHeight(768);
        }
        else
        {
            resources->config->setResolutionWidth(3840);
            resources->config->setResolutionHeight(1024);
        }
    }
    else
    {
        if (currentChoice == 201)
        {
            resources->config->setResolutionWidth(800);
            resources->config->setResolutionHeight(600);
        }
        else if (currentChoice == 202)
        {
            resources->config->setResolutionWidth(1024);
            resources->config->setResolutionHeight(768);
        }
        else
        {
            resources->config->setResolutionWidth(1280);
            resources->config->setResolutionHeight(1024);
        }
    }
    return true;
}

// Changes the current input device based upon what the user has selected
bool MenuOptions::clickInputDevice(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
    int currentChoice = ((CEGUI::RadioButton*)((const CEGUI::WindowEventArgs&)e).window)->getSelectedButtonInGroup()->getID();
    if (currentChoice == 301)
    {
        resources->current_device = (InputDevice *)resources->mouse;
    }
    else if (currentChoice == 302)
    {
        resources->current_device = (InputDevice *)resources->keyboard;
    }
    else
    {
        resources->current_device = (InputDevice *)resources->joystick;
    }
    return true;
}

// Changes the current skybox type based upon what the user has selected
bool MenuOptions::clickSkybox(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
    int currentChoice = ((CEGUI::RadioButton*)((const CEGUI::WindowEventArgs&)e).window)->getSelectedButtonInGroup()->getID();
    if (currentChoice == 401)
    {
        resources->config->setSkyBoxMode(true);
    }
    else
    {
        resources->config->setSkyBoxMode(false);
    }
    return true;
}

// Changes the current FSAA mode based upon what the user has selected
bool MenuOptions::clickFSAA(const CEGUI::EventArgs &e)
{
	resources->audio->playSource(AUDIO_MENU_CLICK);
    int currentChoice = ((CEGUI::RadioButton*)((const CEGUI::WindowEventArgs&)e).window)->getSelectedButtonInGroup()->getID();
    if (currentChoice == 501)
    {
		resources->config->setFSAA("0");
    }
	else if (currentChoice == 502)
    {
		resources->config->setFSAA("2");
    }
	else if (currentChoice == 503)
    {
		resources->config->setFSAA("4");
    }
    else
    {
        resources->config->setFSAA("6");
    }
    return true;
}

// Sets the FSM based on the FSM checkbox
bool MenuOptions::clickFSM(const CEGUI::EventArgs &e)
{
	resources->audio->playSource(AUDIO_MENU_CLICK);
	if (((CEGUI::Checkbox*)((const CEGUI::WindowEventArgs&)e).window)->isSelected())
	{
		resources->config->setFSM(true);
	}
	else
	{
		resources->config->setFSM(false);
	}
	return true;
}

// Changes the current volume of the BGM audio
bool MenuOptions::changeBGM(const CEGUI::EventArgs &e)
{
    resources->config->setVolumeBGM(((CEGUI::Slider*)((const CEGUI::WindowEventArgs&)e).window)->getCurrentValue());
    resources->audio->setVolumeBGM(resources->config->getVolumeBGM());
    return true;
}

// Changes the current volume of the SFX audio
bool MenuOptions::changeSFX(const CEGUI::EventArgs &e)
{
    resources->config->setVolumeSFX(((CEGUI::Slider*)((const CEGUI::WindowEventArgs&)e).window)->getCurrentValue());
    resources->audio->setVolumeSFX(resources->config->getVolumeSFX());
    return true;
}

